/* MeanShift.h
-----------------------------------------
By: 	Wei YE ( ye0003ei@e.ntu.edu.sg )

Date:	10/Oct/2012
-----------------------------------------
*/

#pragma once
#define _CRT_SECURE_NO_DEPRECATE 

#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;

const float EPSILON = 0.01f;
const int   MAX_ITR = 100;

//------------------------------------------------------------------------------
// class MS_Point
// Note that MS_Point will NEVER NEVER EVER create a new float array, it should 
// be initialized by a pointer to a existing float array. Thus there is no need
// for MS_Point to release memory in its deconstructor, this should be done out- 
// side the class by the 'real owner' of the float array.
//------------------------------------------------------------------------------
class MS_Point
{
public:
	float* data_;
	unsigned int dim_;

	MS_Point(){
		data_ = NULL;
		dim_  = 0;
	};

	MS_Point(float* data, unsigned int dim){
		data_ = data;
		dim_ = dim; 
	};

	//~MS_Point(){
	//	if( data_ ) delete []data_;
	//};

	MS_Point& operator=(MS_Point& p2){ // p2 = p, without data copy
		data_ = p2.data_;
		dim_ = p2.dim_;
		return *this;
	};

	void cloneTo(MS_Point& p2){        // p2 = p, with data copy
		//if( !p2.data_ || p2.dim_ != dim_)
		//{
		//	cerr<<"invalid p2!"<<endl;
		//	abort();
		//}
		for(unsigned int d = 0; d < dim_; d++){
			p2.data_[d] = data_[d]; 
		}
	};

	void zero()
	{
		if(dim_ > 0 && data_)
			memset(data_, 0, dim_*sizeof(float));
	};

	MS_Point& operator+=(MS_Point& p2)
	{
		/*if(dim_ != p2.dim_){
			cerr<<"+=, dimensions do not match!"<<endl;
			abort();
		}*/
		for(unsigned int d = 0; d < dim_; d++)
			data_[d] += p2.data_[d];
		return *this;
	};

	inline MS_Point& operator-=(MS_Point& p2)
	{
		/*	if(dim_ != p2.dim_){
		cerr<<"-=, dimensions do not match!"<<endl;
		abort();
		}*/
		for(unsigned int d = 0; d < dim_; d++)
			data_[d] -= p2.data_[d];
		return *this;
	};

	MS_Point& operator/=(float div){
		for(unsigned d = 0; d < dim_; d++){
			data_[d] /= div;
		}
		return *this;
	};

	inline unsigned int dim(){
		return dim_;
	};
};

class MeanShift
{
public:
	MeanShift()
	{
		haspoints_ = false;
		points_ = NULL;
		convpts_ = NULL;
	};

	~MeanShift()
	{
		if( haspoints_ ){
			delete []points_;
			delete []convpts_;
		}
	};
	
	float* getConvPts()
	{
		return convpts_;
	};

	void LoadPoints(float* data, int n_points, int n_dim);

	void NonGridMsFilter();

	void GridMsFilter(int height, int width, int sigmas, int sigmar);

private:
	MS_Point* points_;
	float*    convpts_;
	bool      haspoints_;
	int       n_; // number of points
	int		  d_; // dimension of point
};


